console.log('--------------模块化引1用start--------------');
//<script type="module" src="es6.js"></script> //要设置：type="module"
//1.导入方式
import * as mokuai from "./es6-mokuaihua.js";
console.log("调用模块化1：", mokuai.username1);
console.log("调用模块化2：", mokuai.username2);
console.log("调用模块化3：", mokuai.default.username3);

//2.结构赋值形式
import {username1 as username11, getFun1} from "./es6-mokuaihua.js"; //as 别名，遇到名称出现重复可以起别名
console.log("获取结构形式属性：", username11);  
console.log("获取结构形式方法：", getFun1);

import {default as mokuai3} from "./es6-mokuaihua.js"; 
console.log("获取结构形式属性(默认形式)：", mokuai3.username3);  
console.log("获取结构形式方法(默认形式)：", mokuai3.getFun3);

//3.简便形式、只针对默认暴露export default
import mokuai3_1 from "./es6-mokuaihua.js";
console.log("简便形式：", mokuai3_1.username3);  
console.log("简便形式：", mokuai3_1.getFun3);

//4.直接调用指定js下的属性：
import('./es6-mokuaihua.js').then(modele => {
    console.log("直接调用模块指定属性：", modele.username1);
});

console.log('--------------模块化引用end--------------');

window.onload = function(){
    /*
        let(块级变量)
        const(常量变量) 必须赋初始值、变量值不可修改、块级变量、变量名推荐大写
    */

    //let特性(批量声明变量与数组赋值)
    const C1 = ['张三','李四']; //声明常量
    let[zhangsan, lisi] = C1; //定义2个块级变量、再按顺序进行赋值
    console.log("zhangsan: %s, lisi: %s", zhangsan, lisi);

    //let特性(批量声明变量与对象赋值)
    const C2 = {name:'张三', age:18};
    let{age, name} = C2; //变量名一致则进行赋值
    console.log("name: %s, age: %s", name, age);

    //let特性(模板字符串关键字：``)//可以换行写代码、还可以用${变量名}进行拼接
    let let_1 = '张三';
    let let_2 = `你是谁?
                我是${let_1},   你是谁?`;
    console.log(let_2);

    const C3 = {
        let_1, let_2, //直接把变量名拿过来使用、变量值可以忽略
        improve(){ //定义函数、原本function improve(){}、现在可以忽略function
            console.log('我是特性方法、可以忽略function关键字');
        }
    }
    console.log(C3);

    //变量设置方法改进
    let l_fun = () => {}; //原本 let l_fun = function(){};

    
    //ES6特性替代arguments
    function restFun(a, b, ...args){
        console.log("a: %s, b: %s, args: %s", a, b, args);
    }
    restFun(1,2,3,4,5);
 
    restFun(...['aa','bb','cc','dd']);//也可直接传数组、等价于restFun('aa','bb','cc','dd');

    //数组的特性
    const kuaizi = [`王太利`,'肖英'];
    const fhcq = [`曾毅`,'零花'];
    const hebing1 = kuaizi.concat(fhcq); //原生方式合并
    const hebing2 = [...kuaizi, ...fhcq];//ES6方式合并

    const divArr = [...document.querySelectorAll('div')]; //将伪数组转换为真正数组

    // const p = new Promise((resolve, reject) => {
    //     /*里面的代码在创建对象时就会被执行、并且是异步执行
    //     默认初始状态为：pending(待定), 后面要么fulfilled(兑现)、要么rejected(拒绝),
    //     如果resolve()与reject()同时放开只会触发一个
    //     */
    //    // resolve('成功信息');  //成功回调
    //     reject(new Error('失败信息'));   //失败回调
    // });
    
    // p.then((res) => { //p的异步成功回调
    //     console.log("成功回调：%s", res);
    // }).catch(error => { //p的异步失败回调
    //     console.dir(error);//详细打印
    //     //console.error(error.message);
    // });


    let s1 = new Set(['o','c','b','a','h','a','j']); //有序不重复集合
    console.log("s1: ",s1);    //打印s1
    //console.log('set转为数组: ', [...s1]);   //set转为数组
    //for(let v of s1) console.log(v); //遍历
    // s1.add('d'); //添加
    // s1.delete('b'); //删除
    // s1.has('b'); //判断是否存在、返回boolen
    // s1.clear(); //清空集合

    let s2 = new Set(['x','a','c','h','s','f','c']); 
    console.log("s2: ",s2);    //打印s2
    console.log('交集:',  [...s1].filter(item => s2.has(item))); //获取交集、在2个数组中都存在则为交集
    console.log('并集:',  new Set([...s1,...s2])); //数组合并、并去重
    console.log('差集:',  [...s1].filter(item => !s2.has(item))); //获取差集、获取s1在s2中不存在的


console.log('--------------map学习--------------');
    let m1 = new Map();
    m1.set("name", "张三").set('age', 29); //添加属性
    m1.get("name");//获取指定属性
    m1.size;    //map大小
    //m1.delete('name'); //删除指定属性
    //m1.clear();//清空
    for(let k of m1.keys()) console.log('遍历key:', k);
    for(let v of m1.values()) console.log('遍历value:', v);
    
console.log('--------------继承--------------');
    //js原版继承
    /*
    function Phone(brand, price){   //父类
        this.brand = brand;
        this.price = price;
        
    }
    Phone.prototype.getPhone = function(){
        console.log('我可以打电话,%s', this.brand);
    }
    function SmartPhone(brand, price, color, size){ //子类
        Phone.call(this, brand, price); //继承Phone的属性并赋值
        this.color = color;
        this.size = size;
    }
    SmartPhone.prototype = new Phone;//给对象原型设置Phone、如果不设置就无法调用chuizi.getFun();
    const chuizi = new SmartPhone('锤子',2499,'绿色','5cm');
    console.log('chuizi:', chuizi);
    chuizi.getPhone();*/

    //ES6方式
    class Phone{ //父类
        constructor(brand, price){ //构造方法
            this.brand = brand;
            this.price = price;
        }
        getPhone(){console.log('我可以打电话,%s', this.brand);} //父类方法函数
    }

    class SmartPhone extends Phone{ //子类、同时继承Phone父类
        #version; //私有属性
        constructor(brand, price, color, size, version){ //子类构造方法函数
            super(brand, price); //给父类属性赋值、
            this.color = color;
            this.size = size;
            this.#version = version; //私有属性赋值
        }
        getPhoto(){console.log('拍照');} //定义方法函数

        set name(x){name = x;}  //定义set方法、方法名与属性名保持一致
        get name(){return name;}//定义get方法、方法名与属性名保持一致
        
    }
    const xiaomi = new SmartPhone('小米',799,'绿色','7cm','v1.1');
    console.log('xiaomi:',xiaomi);
    xiaomi.getPhone(); //父类方法调用
    xiaomi.getPhoto(); //子类方法调用
    xiaomi.name = '李四';   //set赋值
    console.log(xiaomi.name); //获取get

console.log('--------------数值扩展--------------');
    function equal(a,b) {return Math.abs(a-b) < Number.EPSILON;};
    console.log(equal(0.1+0.2, 0.3)); //2个整数比较是否相等
    Number.isInteger(5); //判断数值是不是整数、返回：boolean
    Math.trunc(3.5); //去掉小数、返回3
    Math.sign(100); //检测数值返回结果：0:零,1正数,-1负数
    

console.log('--------------对象合并--------------');
    const c1 = {host:"localhostc1", port: 3306};
    const c2 = {host:"localhostc2", url: "/test"};
    Object.assign(c1,c2); //将c2的属性合并到c1,重名的则替换value值
    console.log("c1", c1); //c1结果：{host: 'localhostc2', port: 3306, url: '/test'}


    const arr = ['西游戏','红楼梦','三国演义','水浒传'];
    console.log("是否存在：%s",arr.includes('金瓶梅')); //存在返回true否则false

/*
console.log('--------------async异步使用--------------');
    async function fn() {   //会返回Promise对象
        return '异步返回';  //成功会自动调用、resolve();
        //throw new Error('报错返回');  //异常会自动调用reject();
    }
    fn().then(res => {//成功回调
        console.log(res);
    }).catch(error => { //失败异常回调
        console.error(error);
    });

console.log('--------------await同步使用--------------'); 
    const p1 = new Promise((resolve, reject) => {
        resolve("成功回调p1");
        //reject(new Error("失败回调p1"));
    });
    const p2 = new Promise((resolve, reject) => {
        resolve("成功回调p2");
        //reject(new Error("失败回调p2"));
    });

    //await必须要放在async函数中
    async function main(){
        try {
            let rp1 = await p1;
            let rp2 = await p2;
            console.log(rp1);
            console.log(rp2);
        } catch (e) {
            console.error(e);
        }
    }
    main();//调用
    */

console.log('--------------ES8特性--------------');

    const school = {name: "张三",hobby: ["旅游","打游戏"]}; //创建一个对象
    Object.keys(school); //获取对象所有健、返回数组
    Object.values(school); //获取对象所有值、返回数组
    new Map(Object.entries(school)); //对象所有属性转换为Map集合
   
console.log('--------------ES9对象合并--------------');
const d1 = {name:"张三"}; //创建对象1
const d2 = {age:18, name:"李四"}; //创建对象2
const d3 = {sex:"男",hobby:["旅游","打游戏"]}; //创建对象3
const mangseng = {...d1,...d2,...d3}; //结果:{name: '李四', age: 18, sex: '男', hobby: Array(2)}
console.log("ES9对象合并：",mangseng);

console.log('--------------ES10对象合并--------------');
const arr1 = [1,2,3,[4,5,6,[7,8,9]]];
//将多维数组降维,0不做改变, 1将二维变1维, 2:将2维3维数组变1维,测试结果：[1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(arr1.flat(2));

console.log('--------------ES11--------------');    
const p1 = new Promise((resolve, reject) => {
    resolve("商品数据1");
    //reject(new Error("出错了1"));
});
const p2 = new Promise((resolve, reject) => {
    resolve("商品数据2");
});

const allSettled = Promise.allSettled([p1,p2]); //返回永远都是成功、一个Promise出错,不影响其它的Promise正常返回结果
allSettled.then(res => {
    for(let v of res){  //遍历p1和p2的结果
        console.log("allSettled-res", v); 
    }
}).catch(err => { //allSettled 不会出现reject调用的
    console.error("allSettled-err", err); 
});

const all = Promise.all([p1,p2]); //必须全部成功才可以执行then、否则就会走catch
all.then(res => {
    for(let v of res){  //遍历p1和p2的结果
        console.log("all-res", v); 
    }
}).catch(err => { //allSettled 不会出现reject调用的
    console.error("all-err", err); 
});


const dd = {
    db: {
        host: "127.0.0.1"
        ,username: "root"
    }
};

function main(config){
    let dbHost = config?.db?.host; 
    console.log("dbHost：",dbHost); //获取对象中的host、如果config没传也不会报错
};

main(dd); //调用


let maxNum = Number.MAX_SAFE_INTEGER; //int最大数值
console.log("初始值:", maxNum);
console.log("正常运算+1：", maxNum + 1);
console.log("正常运算+2：", maxNum + 2);
console.log("大数值运算+1：",BigInt(maxNum) + BigInt(1));
console.log("大数值运算+2：",BigInt(maxNum) + BigInt(2));


}






